package com.server.core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.server.runtime.simulationImpl;
import com.server.runtime.teamImpl;
import com.server.runtime.vehicleImpl;

import combat.protocol.data.DoublePoint;
import combat.protocol.data.PhysicalObject;
import combat.protocol.interfaces.OnboardSystemInt;
import combat.protocol.interfaces.OrderInt;
import combat.protocol.types.PhysicalObjectType;
import combat.protocol.types.VehicleType;

public class DocLoader {
	
	private static Map<String, PhysicalObject> referenceMap = new HashMap<String, PhysicalObject>();
	private static Map<String, teamImpl> teams = new HashMap<String, teamImpl>();
	
	public static Element loadFile(String fileName) throws Exception {
		// Get the XML Document
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = dbf.newDocumentBuilder();
		Document dom = db.parse("resources/scenario/"+ fileName +".xml");
		Element docElement = dom.getDocumentElement();
		
		System.out.println("UPDATE: The XML file is loaded");
		
		return docElement;
	}
	
	public static void loadTeams(Element docElement) {
		// Get a list with PhysicalObjects in the XML
		NodeList teamNodeList = docElement.getElementsByTagName("Team");
		
		if(teamNodeList != null && teamNodeList.getLength() > 0)
		{
			System.out.println("UPDATE: Loading teams");
			for(int i = 0; i < teamNodeList.getLength(); i++)
			{
				Element teamElement = (Element) teamNodeList.item(i);
				
				String name = teamElement.getAttribute("name");
				String reference = teamElement.getAttribute("reference");
				
				teamImpl team = new teamImpl();
				team.setTeamName(name);
				simulationImpl.getReference().addTeam(team);
				teams.put(reference, team);
				
				System.out.println("UPDATE: Team ("+name+") loaded");
			}
			System.out.println("UPDATE: Done loading team\n");
		}
	}
	
	public static void loadVehicles(Element docElement) throws Exception {
		NodeList poNodeList = docElement.getElementsByTagName("PhysicalObject");
			
		if(poNodeList != null && poNodeList.getLength() > 0) {
			System.out.println("UPDATE: Loading vehicles");
			// Loop trough all PhysicalObjects
			for(int i=0; i < poNodeList.getLength(); i++) {
				
				// Get the element
				Element poElement = (Element)poNodeList.item(i);
				
				if(poElement.getAttribute("type").equals("vehicle")) {
					// Get the name and x,y parameters from the xml nodes
					String naam = poElement.getElementsByTagName("name").item(0).getFirstChild().getTextContent();
					double x = Double.parseDouble(poElement.getElementsByTagName("x").item(0).getFirstChild().getTextContent());
					double y = Double.parseDouble(poElement.getElementsByTagName("y").item(0).getFirstChild().getTextContent());
					double direction = Double.parseDouble(poElement.getElementsByTagName("direction").item(0).getFirstChild().getTextContent());					
					System.out.println("UPDATE: Loading vehicle: " + naam);
					
					// Create the Vehicle instance by its type
					String type = poElement.getElementsByTagName("vehicleType").item(0).getFirstChild().getTextContent();
					vehicleImpl vehicle = null;
					
					ArrayList<OrderInt> orderList = new ArrayList<OrderInt>();
					ArrayList<OnboardSystemInt> onboardSystem = new ArrayList<OnboardSystemInt>();
					
					if(type.equals("FRIGATE")) {						
						//create frigate
						vehicle = new vehicleImpl(naam, new DoublePoint(x,y), 0, direction, 0.0, 100.0, 100, false, VehicleType.FRIGATE, PhysicalObjectType.VEHICLE, orderList, onboardSystem);
						vehicle.setLocked(false);
					} else if(type.equals("SUBMARINE")) {						
						//create submarine
						vehicle = new vehicleImpl(naam, new DoublePoint(x,y), -1, direction, 0.0, 100.0, 100, false, VehicleType.SUBMARINE, PhysicalObjectType.VEHICLE, orderList, onboardSystem);
						vehicle.setLocked(false);
					} else {// no weaponsSystems
						vehicle = new vehicleImpl(naam, new DoublePoint(x,y), 0, direction, 0.0, 100.0, 100, false, VehicleType.CONVOY, PhysicalObjectType.VEHICLE, orderList, onboardSystem);
					}
			
					// Check if a reference exists and if so, add it to the referenceMap
					Node referenceElement = poElement.getElementsByTagName("reference").item(0);
					
					if(referenceElement != null) {
						referenceMap.put(referenceElement.getFirstChild().getTextContent(), vehicle);
					}
					
					int team = Integer.parseInt(poElement.getElementsByTagName("team").item(0).getFirstChild().getTextContent());
					
					//Parse Orders
					NodeList ordersNodeList = poElement.getElementsByTagName("Order");
					if(ordersNodeList != null && ordersNodeList.getLength() > 0) {
						System.out.println("UPDATE: Loading orders");
						for(int z=0; z < ordersNodeList.getLength(); z++) {
							Element orderElement = (Element)ordersNodeList.item(z);
							if(orderElement.getAttribute("type").equals("move")) {
								double moveX = Double.parseDouble(orderElement.getElementsByTagName("x").item(0).getFirstChild().getTextContent());
								double moveY = Double.parseDouble(orderElement.getElementsByTagName("y").item(0).getFirstChild().getTextContent());
								double speed = Double.parseDouble(orderElement.getElementsByTagName("speed").item(0).getFirstChild().getTextContent());
								try {
									vehicle.orderMove(0, (Object) new DoublePoint(moveX, moveY), (int)speed);
								} catch(Exception e){
									System.out.println("ERROR: Calculation fail.");
								}
							}

						}
						System.out.println("UPDATE: Done loading orders\n");
					}

					simulationImpl.getReference().getTeams().get(team).addVehicle(vehicle);
				}
			}
			//Server message
			System.out.println("UPDATE: Done loading vehicles\n");
		}
	}
}
